package cn.jsxz.common.utils.WeiXinUtil;

import cn.hutool.setting.dialect.Props;
import cn.jsxz.common.utils.HttpRequsetUtil.HttpRequest;
import cn.jsxz.common.utils.JiaMi.MD5Util;
import cn.jsxz.entity.OrderInfo;
import cn.jsxz.entity.SignInfo;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * <p>Title:</p>
 * <p>Description: 微信支付工具类</p>
 *
 * @version 1.0
 */
public class WxPayUtil {

    /**
     * 下单接口
     *
     * @throws Exception
     */
    public static String xiadan(OrderInfo orderInfo) throws Exception {

        String sign = Signature.getSign(orderInfo);

        orderInfo.setSign(sign);

        String result = HttpRequest.sendPost("https://api.mch.WeiXinUtil.qq.com/pay/unifiedorder", orderInfo);

        return result;
    }

    /**
     * 再签名
     *
     * @throws Exception
     */
    public static JSONObject signPrepay(String repay_id) throws Exception {

        Props props = new Props("workConfig.properties", "utf-8");
        String key = props.getStr("appSignKey");
        SignInfo signInfo = new SignInfo();
        JSONObject json = new JSONObject();
        signInfo.setAppId(props.getStr("APPID"));
        long time = System.currentTimeMillis() / 1000;
        signInfo.setTimeStamp(String.valueOf(time));
        signInfo.setNonceStr(RandomStringUtils.randomAlphanumeric(32));
        signInfo.setRepay_id("prepay_id=" + repay_id);
        signInfo.setSignType("MD5");
        json.put("appId", signInfo.getAppId());
        json.put("timeStamp", signInfo.getTimeStamp());
        json.put("nonceStr", signInfo.getNonceStr());
        json.put("package", signInfo.getRepay_id());
        json.put("signType", signInfo.getSignType());
        String result = "";
        result += "appId=" + signInfo.getAppId();
        result += "&nonceStr=" + signInfo.getNonceStr();
        result += "&package=" + signInfo.getRepay_id();
        result += "&signType=" + signInfo.getSignType();
        result += "&timeStamp=" + signInfo.getTimeStamp();
        result += "&key=" + key;
        result = MD5Util.MD5Encode(result, null).toUpperCase();
        json.put("paySign", result);

        return json;
    }

    /**
     * 申请退款，内部添加了随机字符串nonce_str和签名sign
     * @param params 参数map，内部添加了随机字符串nonce_str和签名sign
     * @param paternerKey 商户密钥
     * @param certPath 证书文件目录
     * @return map
     */
//    public static Map<String, String> refund(Map<String, String> params, String paternerKey, String certPath) {
//        params.put("nonce_str", System.currentTimeMillis() + "");
//        String sign = PaymentKit.createSign(params, paternerKey);
//        params.put("sign", sign);
//        String partner = params.get("mch_id");
//        String xmlStr = HttpUtils.postSSL(AppCons.RefundUrl, PaymentKit.toXml(params), certPath, partner);
//        return PaymentKit.xmlToMap(xmlStr);
//    }


    /**
     * 支付结果
     *
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public static Map payResult(HttpServletRequest request, HttpServletResponse response) throws Exception {

        // String result;// 返回给微信的处理结果
        // String inputLine;
        // String notityXml = "";
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        response.setHeader("Access-Control-Allow-Origin", "*");

        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        // // 微信给返回的东西
        // try {
        // while ((inputLine = controller.getRequest().getReader().readLine())
        // != null) {
        // notityXml += inputLine;
        // }
        // controller.getRequest().getReader().close();
        // } catch (Exception e) {
        // e.printStackTrace();
        // }
//		 Map map = doXMLParse11(notityXml);
        return params;
    }

    /**
     * xmlstring字符串转map
     *
     * @param xml
     * @return
     */
    public static Map<String, String> readStringXmlOut(String xml) {
        Map<String, String> map = new HashMap<String, String>();
        Document doc = null;
        try {
            doc = DocumentHelper.parseText(xml); // ½«×Ö·û´®×ªÎªXML
            Element rootElt = doc.getRootElement(); // »ñÈ¡¸ù½Úµã
            @SuppressWarnings("unchecked")
            List<Element> list = rootElt.elements();// »ñÈ¡¸ù½ÚµãÏÂËùÓÐ½Úµã
            for (Element element : list) { // ±éÀú½Úµã
                map.put(element.getName(), element.getText()); // ½ÚµãµÄnameÎªmapµÄkey£¬textÎªmapµÄvalue
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    public static Map<String, String> doXMLParse11(String xml)
            throws XmlPullParserException, IOException {

        InputStream inputStream = new ByteArrayInputStream(xml.getBytes());

        Map<String, String> map = null;

        XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser();

        pullParser.setInput(inputStream, "UTF-8");// ÎªxmlÉèÖÃÒª½âÎöµÄxmlÊý¾Ý

        int eventType = pullParser.getEventType();

        while (eventType != XmlPullParser.END_DOCUMENT) {
            switch (eventType) {
                case XmlPullParser.START_DOCUMENT:
                    map = new HashMap<String, String>();
                    break;

                case XmlPullParser.START_TAG:
                    String key = pullParser.getName();
                    if (key.equals("xml"))
                        break;
                    String value = pullParser.nextText();
                    map.put(key, value);
                    break;
                case XmlPullParser.END_TAG:
                    break;
            }
            eventType = pullParser.next();
        }
        return map;
    }

    /**
     * 返回xml给微信
     *
     * @param return_code
     * @param return_msg
     * @return
     */
    public static String setXml(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]>"
                + "</return_code><return_msg><![CDATA[" + return_msg
                + "]]></return_msg></xml>";
    }

    /**
     * 加载证书
     *
     * @param path
     * @throws IOException
     * @throws KeyStoreException
     * @throws UnrecoverableKeyException
     * @throws NoSuchAlgorithmException
     */
    public static void initCert(String path) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {

        //连接超时时间，默认10秒
        int socketTimeout = 10000;

        //传输超时时间，默认30秒
        int connectTimeout = 30000;

        //请求器的配置
        RequestConfig requestConfig;

        //HTTP请求器
        CloseableHttpClient httpClient;

        String certLocalPath = "/WEB-INF/cert/apiclient_cert.p12";
        //拼接证书的路径
        path = path + certLocalPath;
        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        Props props = new Props("workConfig.properties", "utf-8");

        //加载本地的证书进行https加密传输
        FileInputStream instream = new FileInputStream(new File(path));
        try {
            keyStore.load(instream, props.getStr("SJID").toCharArray());  //加载证书密码，默认为商户ID
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } finally {
            instream.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, props.getStr("SJID").toCharArray())       //加载证书密码，默认为商户ID
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

        httpClient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();

        //根据默认超时限制初始化requestConfig
        requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();

    }
}
